package com.hbt.android.kotlin.learn

import javax.security.auth.Subject


// Kotlin 类可以包含：构造函数和初始化代码块、函数、属性、内部类、对象声明。
// Kotlin 中使用关键字 class 声明类，后面紧跟类名：
class Test {

}

// 定义一个空类
class Empty

// 可以在类中定义成员函数
class Site {

    // 成员变量
    var name: String = "test"
    var url: String = "www.123.cm"


    // 成员函数
    fun siteFun() {
        println("siteFun")
    }
}

class Person {

    var lastName: String = "zhangsan"
        get() = field.toUpperCase()
        set

    var no: Int = 10
        get() = field
        set(value) {
            if (value < 10) {
                field = value
            } else {
                field = -1
            }
        }

    var height: Float = 145.4f
        private set
}

public class MyTest {

    // 非空属性必须在定义的时候初始化,kotlin提供了一种可以延迟初始化的方案,使用 lateinit 关键字描述属性
    lateinit var subject: Subject

//    @Setup
    fun setup() {
        subject = Subject()
    }
}

/**
 * 主构造器中不能包含任何代码，初始化代码可以放在初始化代码段中，初始化代码段使用 init 关键字作为前缀。
 *
 */
class Person2 constructor(firstName: String) {
    init {
        println(firstName)
    }
}

class Site3 constructor(name: String) {
    var url: String = "http://www.runoob.com"
    var country: String = "CN"
    var siteName = name

    init {
        println("初始化： $name")
    }

    // 次构造函数
    constructor (name: String, alexa: Int) : this(name) {
        println("Alexa 排名 $alexa")
    }


    fun test() {
        println("测试方法：$")
    }
}


/**
 *  抽象类
 *  抽象是面向对象编程的特征之一，类本身，或类中的部分成员，都可以声明为abstract的。抽象成员在类中不存在具体的实现。
 */

open class Base {
    open fun test() {

    }
}

abstract class Derived : Base() {
    abstract fun f()
}


/**
 * 嵌套类
 */
class Outer {

    private val bar: Int = 1

    class Nested {
        fun test() = 2
    }
}


/**
 * 内部类
 */
class Outer2 {

    private val bar: Int = 1

    var v = "成员属性"

    /**嵌套内部类**/
    inner class Inner {

        fun test() = bar  // 访问外部类成员

        fun innerTest() {

            var o = this@Outer2 //获取外部类的成员变量

            println("内部类可以引用外部类的成员，例如：" + o.v)
        }
    }
}


/**
 * 匿名内部类
 * 使用对象表达式来创建匿名内部类
 */
class Test1 {
    var v = "成员属性"

    fun setInterFace(test: TestInterFace) {
        test.test()
    }
}
/**
 * 定义接口
 */
interface TestInterFace {
    fun test()
}


/**
 * 类的修饰符
 */
//类的修饰符包括 classModifier 和_accessModifier_:
//
//classModifier: 类属性修饰符，标示类本身特性。
//
//abstract    // 抽象类
//final       // 类不可继承，默认属性
//enum        // 枚举类
//open        // 类可继承，类默认是final的
//annotation  // 注解类
//accessModifier: 访问权限修饰符
//
//private    // 仅在同一个文件中可见
//protected  // 同一个文件中或子类可见
//public     // 所有调用的地方都可见
//internal   // 同一个模块中可见

fun main() {
    // 使用构造函数创建类实例
    val site = Site()

    // 要使用一个属性，只要用名称引用它即可
    site.name
    site.url


    // Person
    var person: Person = Person()

    person.lastName = "wang"

    println("lastName:${person.lastName}")

    person.no = 9
    println("no:${person.no}")

    person.no = 20
    println("no:${person.no}")


    // Site3
    val site3 =  Site3("菜鸟教程")
    println(site3.siteName)
    println(site3.url)
    println(site3.country)
    site3.test()


    // 匿名内部类
    var test = Test1()

    /**
     * 采用对象表达式来创建接口对象，即匿名内部类的实例。
     */
    test.setInterFace(object : TestInterFace {
        override fun test() {
            println("对象表达式创建匿名内部类的实例")
        }
    })

}